package com.alit.face.koala.websocket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

@ServerEndpoint(value = "/notify/{id}")
@Component
public class NotifyWebSocket {
  // 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
  private static int onlineCount = 0;
  // concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
  private static CopyOnWriteArraySet<NotifyWebSocket> webSocketSet = new CopyOnWriteArraySet<>();
  // 与某个客户端的连接会话，需要通过它来给客户端发送数据
  private Session session;
  // 客户端id
  private String id;

  // 连接建立成功调用的方法
  @OnOpen
  public void onOpen(Session session, @PathParam("id") String id) {
    this.session = session;
    this.id = id;
    webSocketSet.add(this); // 加入set中
    addOnlineCount(); // 在线数加1
    System.out.println("连接建立成功:" + id + ",总连接数是:" + getOnlineCount());
  }

  // 连接关闭调用的方法
  @OnClose
  public void onClose() {
    webSocketSet.remove(this); // 从set中删除
    subOnlineCount(); // 在线数减1
    System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
  }

  // 收到客户端消息后调用的方法
  @OnMessage
  public void onMessage(String message, Session session) {
    System.out.println("来自客户端的消息:" + message);
  }

  // 发生错误时调用
  @OnError
  public void onError(Session session, Throwable error) {
    System.out.println("发生错误");
    error.printStackTrace();
  }

  // 群发自定义消息
  public void sendAll(String message) {
    for (NotifyWebSocket item : webSocketSet) {
      try {
        item.session.getBasicRemote().sendText(message);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  // 向指定客户端发送文本消息
  public boolean sendText(Session session, String string) {
    try {
      session.getBasicRemote().sendText(string);
      return true;
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }
  }

  // 向指定客客户端发送文本消息
  public boolean sendText(String id, String message) {
    for (NotifyWebSocket item : webSocketSet) {
      if (item.id.equals(id)) {
        return sendText(item.session, message);
      }
    }
    return false;
  }

  public List<String> getIds() {
    int length = webSocketSet.size();
    List<String> ids = new ArrayList<>(length);
    for (NotifyWebSocket item : webSocketSet) {
      ids.add(item.id);
    }
    return ids;
  }

  public synchronized int getOnlineCount() {
    return onlineCount;
  }

  public synchronized void addOnlineCount() {
    onlineCount++;
  }

  public synchronized void subOnlineCount() {
    onlineCount--;
  }
}